#include <workflow/WFFacilities.h>
#include <wfrest/HttpServer.h>
#include <workflow/MySQLUtil.h>
#include <workflow/MySQLResult.h>
#include <signal.h>
#include <iostream>
#include <string>
#include <map>

using std::cout;
using std::cerr;
using std::string;
using std::map;
using std::pair;
static WFFacilities::WaitGroup waitGroup(1);

void shutdown(int signum) {
    cout << "done!\n";
    waitGroup.done();
}

int main() {
    signal(SIGINT, shutdown);

    /**
     * wfrest 的 server 可以默认构造
     * server已经把process写好了，process会根据请求的方法和路径自动创建不同的任务
     */
    wfrest::HttpServer server;

    /* 用户注册 方法+路径+函数对象 */
    server.POST("/file/mupload/init", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        // 在函数对象里面，可以获取请求，设置响应
        resp->String("init");

    });

    server.POST("/file/mupload/uppart", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        // ?uploadID=piaochong&chkidx=4
        map<string, string> queryMap = req->query_list();
        for (auto pair: queryMap) {
            cout << "first = " << pair.first << " second = " << pair.second << "\n";
        }
    });

    server.POST("/file/mupload/complete", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        resp->String("complete");
    });

    server.GET("/header", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        resp->headers["Location"] = "http://www.baidu.com";
        resp->set_status_code("302");
    });

    server.GET("/index.html", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        resp->File("./index.html"); // 部署静态资源服务器
    });

    server.POST("/login", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        // urlencoded格式报文
        map<string, string> urlencodeMap = req->form_kv();
        for (auto pair: urlencodeMap) {
            cout << "first = " << pair.first << " second = " << pair.second << "\n";
        }

        resp->String("ok");
    });

    server.GET("/upload.html", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        resp->File("./upload.html"); // 部署静态资源服务器
    });

    server.POST("/upload", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp) {
        // form-data格式报文
        map<string, pair<string, string>> formdataMap = req->form();
        for (auto formpair: formdataMap) {
            cout << "first = " << formpair.first
                 << "second.first = " << formpair.second.first
                 << "second.second = " << formpair.second.second << "\n";
        }
    });

    server.GET("/mysql", [](const wfrest::HttpReq *req, wfrest::HttpResp *resp, SeriesWork *series) {
        WFMySQLTask *mysqlTask = WFTaskFactory::create_mysql_task(
                "mysql://chizuru:*@db4free.net", 1,
                [resp](WFMySQLTask *mysqlTask) {

                    protocol::MySQLResponse *respMysql = mysqlTask->get_resp();
                    protocol::MySQLResultCursor cursor(respMysql);
                    std::vector<std::vector<protocol::MySQLCell>> rows;
                    cursor.fetch_all(rows);

                    for (auto &row: rows) {
                        for (auto &cell: row) {
                            if (cell.is_int()) {
                                cout << cell.as_int();
                            } else if (cell.is_string()) {
                                cout << cell.as_string();
                            } else if (cell.is_datetime()) {
                                cout << cell.as_datetime();
                            }
                            cout << "\t";
                        }
                        cout << "\n";
                    }
                    resp->String("mysql done!\n");
                });
        string sql = "select * from netdiskdb.users;";
        mysqlTask->get_req()->set_query(sql);
        series->push_back(mysqlTask);
    });


    if (server.track().start(8889) == 0) { //track 开启追踪
        server.list_routes();  //list_routes 列出所有的任务
        waitGroup.wait();
        server.stop();
    } else {
        perror("server start fail");
        return -1;
    }

    cout << "finished!\n";
    return 0;
}
